#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <malloc/malloc.h>
#include <sys/wait.h>
#include "common.h"
#include "test.h"
#include "efi_protocol.h"
#include "menu.h"
#include "strSpliter.h"
#include "utile.h"
#include <stdbool.h>
#include "arithmetic/common.h"


/*
用数组a[100]存放产生的确100个随机整数，数组x[10]来存放个位上的数字分别为
1，2，3，4，5，6，7，8，9，0的数的个数。即个位是1的个数存放在x[1]中，
个位是2的个数存放在x[2]中，……个位是0的个数存放在x[10]。 
*/
int TestRand(int argc, char *argv[]) 
{ 
    int a[101],x[11],i,p; 

    for(i=0;i<=11;i++) 
        x[i]=0; 
    for(i=1;i<=100;i++) 
    { 
        a[i]=rand() % 100; 
        printf("%4d",a[i]); 
        if(i%10==0)printf("\n"); 
    } 

    for(i=1;i<=100;i++) 
    { 
        p=a[i]%10; 
        if(p==0) p=10; 
        x[p]=x[p]+1; 
    } 
    for(i=1;i<=10;i++) 
    { 
        p=i; 
        if(i==10) p=0; 
        printf("%d,%d\n",p,x[i]); 
    } 
    printf("\n"); 
    return 0;
} 


// 求最小公倍数和最大公约数。
// 最小公倍数=两个整数之积/最大公约数
int TestMultiple(int argc, char *argv[])
{
    int m,n,mn,r;
    int ret;

    printf("please enter two data: ");
    printf("m = ");
    ret = scanf("%d",&m);
    if (ret < 0) {
        perror("scanf error");
        return -1;
    }
    printf("n = ");
    ret = scanf("%d",&n);
    if (ret < 0) {
        perror("scanf error");
        return -1;
    }

    if (m < n) {
        r = m;
        m = n;
        n = r;
    }
    mn = m * n;
    r = m % n;

    while (r != 0) {
        m = n;
        n = r;
        r = m % n;
    }
    printf("最大公约数:%d\n",n); 
    printf("最小公倍数:%d\n",mn/n); 

    return 0;
}


//把m作为被除数，将2—sqrt(m)作为除数，如果都除不尽，m就是素数，返回1；否则就不是，返回0。
int Prime(int m)
{
    int i,k;

    k = (int)sqrt(m);
    for (i=2;i<k;i++) {
        if (m % i == 0) {
            return 0;
        }
    }
    return 1;

}

int TestPrime(int argc, char *argv[])
{
    int m;
    int ret;

    printf("please enter the number: ");
    ret = scanf("%d",&m);
    if (ret < 0) {
        perror("scanf error");
        return -1;
    }

    if (Prime(m) == 1){
        printf("%d is a prime.\n",m);
    }
    else{
        printf("%d is not a prime.\n",m);
    }

    return 0;
}


//
int TestGoldbach(int argc, char *argv[])
{
    int i,x;
    int ret;

    printf("please enter the even nuimber(>6): ");
    ret = scanf("%d",&x);
    if (ret < 0) {
        perror("scanf error");
        return -1;
    }

    if (x < 6 || x % 2 !=0) {
        printf("data error!\n");
        return 1;
    }

    for(i=2;i<=x/2;i++){ 
        if (Prime(i)&&Prime(x-i)) { 
            printf("%d+%d\n",i,x-i); 
            printf("验证成功!"); 
            break; 
        } 
    }
    return 0;

}


//
#define	MAXARGS		20				/* cmdline args	*/
#define	ARGLEN		100				/* token length	*/

char *maskstring(char *buf)
{
    char *cp = NULL;

    printf("len = %d\n",(int)strlen(buf));
    buf[strlen(buf) - 1] = '\0';
    
    cp = malloc(strlen(buf) + 1);
    if (cp == NULL) {
        perror("no memory");
        exit (1);
    }
    strncpy(cp,buf,strlen(buf) + 1);

    return cp;    
}

int execute(char *arglist[])
{
    execvp(arglist[0],arglist);
    perror("execute error");
    exit (1);
    return 1;
}

int TestPsh1(int argc, char *argv[])
{
    char *arglist[MAXARGS + 1];
    int numargs = 0;
    char argbuf[ARGLEN];

    while (numargs < MAXARGS) {
        printf("argv[%d]:",numargs);
        if (fgets(argbuf,ARGLEN,stdin) && *argbuf != '\n') {
            arglist[numargs++] = maskstring(argbuf);
        }
        else {
            if (numargs > 0) {
                arglist[numargs] = NULL;
                execute(arglist);
                numargs = 0;
            }
        }
    }
    return 0;
}

//
int Execute_Cmd(char *arglist[])
{
    int pid;

    pid = fork();           // creat a new process

    switch (pid) {
    case -1:
        perror("fork error!\n");
        exit(1);
    case 0:
        execvp(arglist[0],arglist);
        perror("execute error");
        exit (1);
    default:
        while (wait(NULL) != pid);
    }
    return 0;
}

int TestPsh2(int argc, char *argv[])
{
   char *arglist[MAXARGS + 1];
    int numargs = 0;
    char argbuf[ARGLEN];

    while (numargs < MAXARGS) {
        printf("argv[%d]:",numargs);
        if (fgets(argbuf,ARGLEN,stdin) && *argbuf != '\n') {
            arglist[numargs++] = maskstring(argbuf);
        }
        else {
            if (numargs > 0) {
                arglist[numargs] = NULL;
                Execute_Cmd(arglist);
                numargs = 0;
            }
        }
    }
    return 0;   
}

//
char *mystrtok(char *str, char *ctrl) 
{ 
     /*char *p=str,*q=ctrl,*r; 
     while(p&&q&&*p&&*q){ 
         for(r=p,q=ctrl;*r&&*q&&*r==*q;r++,q++); 
         if(q&&*q) p++; // 不匹配，从下一个字符开始比较 
         else {*p='\0'; break;} // 首次找到则返回 
     } 
     return str; 
     */
    int i;
    char c;
    int find_done = 0;
    char *cp = str;

    for (c=*str;c;str++) {
        c = *str;
        for(i=0;ctrl[i];i++) {
            if (c == ctrl[i]) {
                *str = '\0';
                find_done = 1;
                break;
            }
        }
    }
    if (find_done) {
        return cp;
    }
    return NULL;
}

int TestMystrtok(int argc, char *argv[])
{
    char str1[] = "abcdefg";
    //char str2[] = "ef";
    char *p;
    //char *q;
    p = mystrtok(str1,"df");
    //q = mystrtok(str1,str2);

    printf("%s\n",p);
    //printf("%s\n",q);
    return 0;
}

//
int TestProtocol(int argc, char *argv[])
{
    int a=5,b=9;
    EFI_PRO *efi_pro = NULL;

    efi_pro = &EFI_Pro;

    printf("a+b = %d\n",efi_pro->Add(efi_pro,a,b));
    printf("max = %d\n",efi_pro->Max(efi_pro,a,b));

    return 0;
    
}

//
int TestArgs(int argc, char *argv[])
{
    EFI_ARGS *Arg_pro = NULL;
    ARGS arglist;
    int status;

    Arg_pro = &Arg_Protocol;

    status = Arg_pro->Init(Arg_pro,&arglist,100);
    if (status == ERROR) {
        return status;
    }
    
    printf("please enter the command: ");
    status = Arg_pro->GetCmd(Arg_pro,&arglist);
    if (status == ERROR) {
        return status;
    }

    printf("Length = %d\n",Arg_pro->Length(Arg_pro,&arglist));

    status = Arg_pro->Display(Arg_pro,&arglist);
    if (status == ERROR) {
        return status;
    }

    status = Arg_pro->Delete(Arg_pro,&arglist);
    return status;
}

int Testargv(int argc, char *argv[])
{
    char str[100];
    char delimiters[] = " ";
    char **argvs;
    int argcs = 0;
    char *s;

    printf("please enter the command: ");
    
    s = fgets(str, sizeof(str),stdin); 
    if (s == NULL){
        perror("gets error");
        return -1;
    }
          
    if ((argcs = makeargv(str,delimiters,&argvs)) != 0){
        int suffix;
        printf("argc = %d\n",argcs);
        for (suffix=0;suffix<argcs;suffix++) {
            printf("%d:%s\n",suffix,argvs[suffix]);
        }
    }

    freemakeargv(argvs);
    return 0;
}

static void show_buf(int *buf, int len)
{
    if (NULL == buf) {
        return;
    }
    for (int i = 0; i < len; i++) {
        printf("%d%s", buf[i],
                ((i + 1 == len) ? ("\n") : (", ")));
    }
}

static int insertion_sort(int *buf, int len)
{
    int i, j, key;
    for (j = 1; j < len; j++) {
        show_buf(buf, len);
        key = buf[j];
        i = j - 1;
        while (i >= 0 && buf[i] > key) {
            buf[i + 1] = buf[i];
            i--;
        }
        buf[i + 1] = key;
    }
    show_buf(buf,len);
    return 0;
}

int TestInsertion_sort(int argc, char *argv[])
{
    int a[] = {10, 5, 3, 6, 7, 15};
    return insertion_sort(a, LENGTH(a, int));
}

int TestSpliter(int argc, char *argv[])
{
    StrSpliter spliter = getStrSpliter();
    spliter->split(spliter,"a,b,c,d,*e",",");
    spliter->show(spliter);

    spliter->split(spliter, "how$$$$are$you?","$");
    spliter->show(spliter);

    for (int i = 0;i < spliter->length(spliter);++i){
        printf("field[%d]: %s\n", i, spliter->field(spliter, i));
    }

    if (argc == 2) {
        spliter->split(spliter, argv[0], argv[1]);
        spliter->show(spliter);
    }

    spliter->free(spliter);

    return 0;
}

static void print_backward(char *str, int len, int pos)
{
    if (pos == len) {
        return;
    }
    print_backward(str, len, pos + 1);
    putchar(str[pos]);
}

// Print backward via iterator
int TestPrintBackward(int argc, char *argv[])
{
    if (argc == 0) {
        fprintf(stderr, "Usage: printbackward word\n");
        return -1;
    }

    print_backward(argv[0], strlen(argv[0]), 0);
    putchar('\n');
    return 0;
}

int TestTrim(int argc, char *argv[])
{
    const char *s = "  hi how are you?    E N D...   ";
    char str[128];
    strncpy(str, s, strlen(s));
    printf("before trim:%sendOfString\n", str);

    printf("after trim:%sendOfString\n", fastTrim(str));

    return 0;
}

int TestPowerOf2(int argc, char *argv[])
{
    int n = atoi(argv[0]);
    printf("n=%d\n", n);
    bool ret = isPowerOf2(n);
    printf("%d is %s powerOf2\n", n, (ret?"NOT":""));
    return 0;
}

